package cn.hx.whh.automaticticket.scanner;


import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbManager;
import android.util.Log;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import cn.hx.whh.automaticticket.enums.ScannerHeadEnum;
import cn.hx.whh.automaticticket.listener.OnScannerListener;
import cn.hx.whh.automaticticket.utils.ByteUtils;
/**
 OnScannerListener listener = new OnScannerListener(){
    @Override
    public void onScanData(String data, ScannerHeadEnum headEnum){ }
    @Override
    public void onResponseData(String data, ScannerHeadEnum headEnum){}
    @Override
    public void onResponseTimeout(){}
 };
 ScannerHeadProgram scanner = ScannerHeadProgram.getInstance(class.this);
 scanner.initScannerHead(ScannerHeadEnum.radio_broadcast);
 scanner.analysisBroadcast();
 scanner.setScannerListener(listener);

 */

/**
 * 扫码读头程序类,  主要实现读头扫描到的二维码信息
 *
 */
public class ScannerHeadProgram {
    private static final String TAG = "扫码读头程序类";
    private Context context;

    /**
     * 广播开发了吗? 这里需要注意,
     * 这里需要手动设置开发广播  从设备的
     * 设置 --> 扫码与键盘 --> (扫码设备)中修改 --> 勾选 "不输出" 和开启 "广播开启"
     */
    private boolean isBroadcastOpened = false;

    /**
     * 这里就是所有的USB扫码器的Pid,Vid   如果还有外接的,请在这里添加
     */
    private static final List<String> pidVidList = new ArrayList<>(Arrays.asList("4608,1504", "9492,1529", "34,12879", "193,12897"));

    /**
     * 等待答复 ---> 等待命令的返回中, 主要给串口扫码器用, 现在只用于有返回值的指令
     */
    private boolean isWaitResponse = false;

    /**
     *
     */
    private ConcurrentHashMap<String, OnScannerListener> scannerListenerHashMap = new ConcurrentHashMap<>();



    /**
     * 广播接收机
     */
    private BroadcastReceiver broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String data = intent.getStringExtra("data");
            if (data != null && data.length() > 0) {
                if (isResponseData(data, ScannerHeadEnum.radio_broadcast)){
                    Log.i(TAG, "广播接收机: 关于接收机响应数据 ---> " + data);
                    isWaitResponse = false;
                    for (Map.Entry<String,OnScannerListener> entry:scannerListenerHashMap.entrySet()){
                        entry.getValue().onResponseData(data, ScannerHeadEnum.radio_broadcast);
                    }
                }else{
                    Log.i(TAG, "广播接收机: 关于接收机扫描数据 ---> " + data);
                    isWaitResponse = false;
                    for (Map.Entry<String,OnScannerListener> entry:scannerListenerHashMap.entrySet()){
                        entry.getValue().onScanData(data, ScannerHeadEnum.radio_broadcast);
                    }
                }
            }
        }
    };



    private static ScannerHeadProgram scannerHeadProgram;

    private ScannerHeadProgram(Context context) {
        this.context = context;
    }

    /**
     * 获取扫码读头程序,
     * 这里设计成为单例模式。
     *
     * @param context
     * @return
     */
    public synchronized static ScannerHeadProgram getInstance(Context context) {
        ScannerHeadProgram scannerHead;
        if (scannerHeadProgram == null) {
            scannerHeadProgram = new ScannerHeadProgram(context);
            scannerHead = scannerHeadProgram;
        } else {
            scannerHeadProgram.context = context;
            scannerHead = scannerHeadProgram;
        }
        return scannerHead;
    }

    /**
     * 初始化扫码读头
     * 这里默认是做广播类型的
     */
    public synchronized void initScannerHead(ScannerHeadEnum type) {
        if (scannerHeadProgram == null || scannerHeadProgram.context == null) {
            Log.e(TAG, "扫码读头程序或者程序上下文为空");
            return;
        }
        if (this.isBroadcastOpened) {
            Log.e(TAG, "分析广播: 广播已经开启了");
            return;
        }
        int usb_type = 0;// 0:默认 1:键值  2:广播(厂家推荐) 3:直接填充输出
        boolean serial_key_board = true;
        boolean serial_radio_broadcast = true;
        switch (type) {
            case key_board:
                usb_type = 0;
                serial_key_board = true;
                serial_radio_broadcast = false;
                break;
            case radio_broadcast:
                usb_type = 2;
                serial_key_board = false;
                serial_radio_broadcast = true;
                break;
            case key_board_and_radio:
                usb_type = 0;
                serial_key_board = true;
                serial_radio_broadcast = true;
                break;
            default:
                Log.e(TAG, "初始化扫码读头枚举无效");
                return;
        }

        int pid, vid;
        if (this.context != null) {
            HashMap<String, UsbDevice> deviceHashMap = ((UsbManager) this.context.getSystemService(Activity.USB_SERVICE)).getDeviceList();// 获取所有USB扫码器的Pid和Vid
            // 1. 配置 USB扫码器
            if (deviceHashMap != null) {
                for (Map.Entry<String, UsbDevice> entity : deviceHashMap.entrySet()) {
                    pid = entity.getValue().getProductId();
                    vid = entity.getValue().getVendorId();
                    if (pidVidList.contains(pid + "," + vid)) {
                        Intent intent = new Intent();
                        intent.setAction("com.sunmi.scanner.ACTION_BAR_DEVICES_SETTING");
                        intent.putExtra("name", entity.getValue().getDeviceName());
                        intent.putExtra("pid", pid);
                        intent.putExtra("vid", "vid");
                        intent.putExtra("type", usb_type);
                        intent.putExtra("toast", true); // 是否显示调式Toast 开发阶段先写 true
                        this.context.sendBroadcast(intent);
                    }
                }
            }
        }
        // 2. 配置 串口扫码器
        Intent intent = new Intent();
        intent.setAction("com.sunmi.scanner.ACTION_BAR_DEVICES_SETTING");
        intent.putExtra("analog_key", serial_key_board); // true 为开启键盘 keyboard
        intent.putExtra("broadcast", serial_radio_broadcast); // true 为开启广播 broadcast
        intent.putExtra("toast", true); // 是否显示调式Toast 开发阶段先写 true
        this.context.sendBroadcast(intent);
    }


    /**
     * 开启广播数据处理
     */
    public void analysisBroadcast() {
        Log.i(TAG, "开启广播数据处理");
        if (this.isBroadcastOpened) {
            Log.e(TAG, "分析广播: 广播已经开启了");
            return;
        }
        if (this.context == null) {
            Log.e(TAG, "分析广播: 上下文为 null");
            return;
        }
        IntentFilter filter = new IntentFilter();
        filter.addAction("com.sunmi.scanner.ACTION_DATA_CODE_RECEIVED");
        this.context.registerReceiver(broadcastReceiver, filter);
        this.isBroadcastOpened = true;
    }

    /**
     * 判定广播响应信息
     * @param message
     * @param headEnum
     * @return
     */
    private boolean isResponseData(String message, ScannerHeadEnum headEnum){
        Log.i(TAG, "判定广播响应信息[hex]:" + message +"["+ ByteUtils.str2HexString(message) +"]");
        switch (headEnum){
            case key_board: //键值，开头会缺少2字节，这俩是不可见字符：<STX><SOH>
                message = ByteUtils.hexStr2Str(SerialCmd.RES_PREFIX_HEX).substring(0,2) + message;
                break;
            case radio_broadcast: //广播
                break;
            default:
                break;
        }
        return (message.length() > 6 && message.substring(0,6).equals(ByteUtils.hexStr2Str(SerialCmd.RES_PREFIX_HEX)));
    }

    /**
     * 设置扫码器数据监听
     * 注意：这里是支持多个回调的，OnScannerListener实例化多个的话，每个都能收到数据
     * @param listener
     */
    public void setScannerListener(OnScannerListener listener){
        Log.i(TAG, "setScannerListener:" + listener);
        if (listener == null){
            Log.e(TAG, "setScannerListener:listener is null.");
            return;
        }
        scannerListenerHashMap.put(listener.toString(), listener);
    }

    /**
     * 退出程序时释放资源
     */
    public void destory(){
        Log.i(TAG, "destory");
        if (this.context == null || !isBroadcastOpened)
            return;
        try {
            this.context.unregisterReceiver(broadcastReceiver);
            isBroadcastOpened = false;
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}
